package com.example.campuslink.ui.fragment

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.params.StreamConfigurationMap
import android.media.MediaRecorder
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.os.HandlerThread
import android.util.Log
import android.util.Size
import android.view.LayoutInflater
import android.view.Surface
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.bumptech.glide.Glide
import com.example.campuslink.R
import com.example.campuslink.commen.dialog.ShowVideoDialog
import com.example.campuslink.commen.tools.Sp
import com.example.campuslink.commen.tools.SpKey
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*

class RecordFragment : Fragment() {


    companion object {
        private const val TAG = "VideoRecordActivity"
        private const val REQUEST_CODE_PERMISSIONS = 1
        private val REQUIRED_PERMISSIONS = arrayOf(
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        )
    }

    private lateinit var surfaceView: SurfaceView
    private lateinit var recordButton: ImageView
    private var isRecording = false

    private var cameraDevice: CameraDevice? = null
    private var mediaRecorder: MediaRecorder? = null
    private var cameraCaptureSession: CameraCaptureSession? = null
    private var previewSize: Size? = null
    private var videoSize: Size? = null
    private var requestBuilder: CaptureRequest.Builder? = null
    private var previewSurface: Surface? = null
    private var currentVideoPath: String? = null

    private var backgroundThread: HandlerThread? = null
    private var backgroundHandler: Handler? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_record, container, false)

        surfaceView = view.findViewById(R.id.surface)
        recordButton = view.findViewById(R.id.iv_record)

        surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(holder: SurfaceHolder) {
                if (checkPermissions()) {
                    openCamera()
                }
            }

            override fun surfaceChanged(
                holder: SurfaceHolder,
                format: Int,
                width: Int,
                height: Int
            ) {
                // Optional implementation
            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
                closeCamera()
            }
        })

        recordButton.setOnClickListener {
            if (!isRecording) {
                startRecording()
                Glide.with(requireContext()).load(R.drawable.recording_square).into(recordButton)
            } else {
                stopRecording()
                Glide.with(requireContext()).load(R.drawable.recording_cirle).into(recordButton)

                val videoDialog = ShowVideoDialog()
                videoDialog.videoPath = currentVideoPath ?: ""
                videoDialog.show(childFragmentManager, "videoDialog")
            }
            isRecording = !isRecording
        }

        return view
    }

    private fun checkPermissions(): Boolean {
        for (permission in REQUIRED_PERMISSIONS) {
            if (ContextCompat.checkSelfPermission(
                    requireContext(),
                    permission
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                ActivityCompat.requestPermissions(
                    requireActivity(),
                    arrayOf(permission),
                    REQUEST_CODE_PERMISSIONS
                )
                return false
            }
        }
        return true
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                openCamera()
            } else {
                Log.e(TAG, "权限不足，无法开启相机录像")
            }
        }
    }

    @SuppressLint("MissingPermission")
    private fun openCamera() {
        val cameraManager =
            requireContext().getSystemService(Context.CAMERA_SERVICE) as CameraManager
        try {
            val cameraId = cameraManager.cameraIdList[0]
            val characteristics = cameraManager.getCameraCharacteristics(cameraId)
            val map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
                ?: throw RuntimeException("无法获取相机配置信息")

            val surfaceViewWidth = surfaceView.measuredWidth
            val surfaceViewHeight = surfaceView.measuredHeight

            previewSize = chooseOptimalSize(
                map.getOutputSizes(SurfaceHolder::class.java),
                surfaceViewWidth,
                surfaceViewHeight
            )

            cameraManager.openCamera(cameraId, object : CameraDevice.StateCallback() {
                override fun onOpened(camera: CameraDevice) {
                    cameraDevice = camera
                    startPreview()
                }

                override fun onDisconnected(camera: CameraDevice) {
                    camera.close()
                    cameraDevice = null
                }

                override fun onError(camera: CameraDevice, error: Int) {
                    camera.close()
                    cameraDevice = null
                    Log.e(TAG, "相机打开出现错误: $error")
                }
            }, null)
        } catch (e: Exception) {
            Log.e(TAG, "打开相机出现错误: ${e.message}")
        }
    }

    private fun chooseOptimalSize(sizes: Array<Size>?, width: Int, height: Int): Size {
        sizes?.let {
            val sizeList = sizes.filter { size ->
                size.width <= width && size.height <= height
            }.sortedByDescending { it.width * it.height }

            return if (sizeList.isNotEmpty()) sizeList.first() else sizes.first()
        }
        return Size(1920, 1080) // Default size if sizes is null
    }

    private fun startPreview() {
        try {
            val surfaceHolder = surfaceView.holder
            previewSurface = surfaceHolder.surface
            if (previewSurface == null) throw IOException("预览Surface为空")

            val outputSurfaces = listOf(previewSurface)

            requestBuilder =
                cameraDevice?.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)?.apply {
                    addTarget(previewSurface!!)
                }

            cameraDevice?.createCaptureSession(
                outputSurfaces,
                object : CameraCaptureSession.StateCallback() {
                    override fun onConfigured(session: CameraCaptureSession) {
                        cameraCaptureSession = session
                        try {
                            val request = requestBuilder?.build()
                            request?.let {
                                session.setRepeatingRequest(it, null, backgroundHandler)
                            }
                        } catch (e: Exception) {
                            Log.e(TAG, "配置预览出现错误: ${e.message}")
                        }
                    }

                    override fun onConfigureFailed(session: CameraCaptureSession) {
                        Log.e(TAG, "配置预览失败")
                    }
                },
                backgroundHandler
            )
        } catch (e: Exception) {
            Log.e(TAG, "开始预览出现错误: ${e.message}")
        }
    }

    private fun startRecording() {
        try {
            mediaRecorder = MediaRecorder().apply {
                setAudioSource(MediaRecorder.AudioSource.MIC)
                setVideoSource(MediaRecorder.VideoSource.SURFACE)

                setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
                setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
                setVideoEncoder(MediaRecorder.VideoEncoder.H264)

                setOrientationHint(90)

                if (ContextCompat.checkSelfPermission(
                        requireContext(),
                        Manifest.permission.RECORD_AUDIO
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    throw SecurityException("Audio recording permission denied")
                }
                val videoFile = File(
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
                    "${SimpleDateFormat("yyyyMMddHHmmss").format(Date())}.mp4"
                )
                currentVideoPath = videoFile.absolutePath
                setOutputFile(videoFile.absolutePath)

                prepare()
                start()
            }

            val surfaces = listOfNotNull(previewSurface, mediaRecorder?.surface)
            requestBuilder =
                cameraDevice?.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)?.apply {
                    surfaces.forEach { addTarget(it) }
                }

            cameraDevice?.createCaptureSession(
                surfaces,
                object : CameraCaptureSession.StateCallback() {
                    override fun onConfigured(session: CameraCaptureSession) {
                        cameraCaptureSession = session
                        try {
                            val request = requestBuilder?.build()
                            request?.let {
                                session.setRepeatingRequest(it, null, backgroundHandler)
                            }
                        } catch (e: Exception) {
                            Log.e(TAG, "配置预览出现错误: ${e.message}")
                        }
                    }

                    override fun onConfigureFailed(session: CameraCaptureSession) {
                        Log.e(TAG, "配置预览失败")
                    }
                },
                backgroundHandler
            )
        } catch (e: IOException) {
            Log.e(TAG, "录像准备出现错误: ${e.message}")
        } catch (e: Exception) {
            Log.e(TAG, "开始录像出现错误: ${e.message}")
        }
    }

    private fun stopRecording() {
        try {
            mediaRecorder?.apply {
                stop()
                release()
            }
            mediaRecorder = null

            cameraCaptureSession?.apply {
                stopRepeating()
                abortCaptures()
                startPreview()
            }
        } catch (e: Exception) {
            Log.e(TAG, "停止录像后恢复预览出现错误: ${e.message}")
        }
    }

    private fun closeCamera() {
        try {
            cameraDevice?.close()
            cameraCaptureSession?.close()
        } catch (e: Exception) {
            Log.e(TAG, "关闭相机出现错误: ${e.message}")
        } finally {
            cameraDevice = null
            cameraCaptureSession = null
        }
    }

    private fun startBackgroundThread() {
        backgroundThread = HandlerThread("CameraBackground").apply {
            start()
            backgroundHandler = Handler(looper)
        }
    }

    private fun stopBackgroundThread() {
        backgroundThread?.quitSafely()
        try {
            backgroundThread?.join()
            backgroundThread = null
            backgroundHandler = null
        } catch (e: InterruptedException) {
            Log.e(TAG, "停止后台线程出现错误: ${e.message}")
        }
    }

    override fun onResume() {
        super.onResume()
        startBackgroundThread()
        openCamera()
    }

    override fun onPause() {
        super.onPause()
        stopRecording()
        closeCamera()
        stopBackgroundThread()
    }

    override fun onDestroy() {
        super.onDestroy()
        closeCamera()
    }
}
